home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / awt / MenuItem.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  17.4 KB  |  584 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)MenuItem.java    1.57 98/08/31
  3.  *
  4.  * Copyright 1995-1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package java.awt;
  15.  
  16. import java.awt.peer.MenuItemPeer;
  17. import java.awt.event.*;
  18. import java.io.ObjectOutputStream;
  19. import java.io.ObjectInputStream;
  20. import java.io.IOException;
  21.  
  22.  
  23. /**
  24.  * All items in a menu must belong to the class
  25.  * <code>MenuItem</code>, or one of its subclasses.
  26.  * <p>
  27.  * The default <code>MenuItem</code> object embodies
  28.  * a simple labeled menu item.
  29.  * <p>
  30.  * This picture of a menu bar shows five menu items:
  31.  * <IMG SRC="doc-files/MenuBar-1.gif"
  32.  * ALIGN=CENTER HSPACE=10 VSPACE=7>
  33.  * <br CLEAR=LEFT>
  34.  * The first two items are simple menu items, labeled
  35.  * <code>"Basic"</code> and <code>"Simple"</code>.
  36.  * Following these two items is a separator, which is itself
  37.  * a menu item, created with the label <code>"-"</code>.
  38.  * Next is an instance of <code>CheckboxMenuItem</code>
  39.  * labeled <code>"Check"</code>. The final menu item is a
  40.  * submenu labeled <code>"More Examples"</code>,
  41.  * and this submenu is an instance of <code>Menu</code>.
  42.  * <p>
  43.  * When a menu item is selected, AWT sends an action event to
  44.  * the menu item. Since the event is an
  45.  * instance of <code>ActionEvent</code>, the <code>processEvent</code>
  46.  * method examines the event and passes it along to
  47.  * <code>processActionEvent</code>. The latter method redirects the
  48.  * event to any <code>ActionListener</code> objects that have
  49.  * registered an interest in action events generated by this
  50.  * menu item.
  51.  * <P>
  52.  * Note that the subclass <code>Menu</code> overrides this behavior and
  53.  * does not send any event to the frame until one of its subitems is
  54.  * selected.
  55.  *
  56.  * @version 1.57, 08/31/98
  57.  * @author Sami Shaio
  58.  */
  59. public class MenuItem extends MenuComponent {
  60.  
  61.     static {
  62.         /* ensure that the necessary native libraries are loaded */
  63.     Toolkit.loadLibraries();
  64.         initIDs();
  65.     }
  66.  
  67.     /**
  68.      * A value to indicate whether a menu item is enabled
  69.      * or not.  If it is enabled, <code>enabled</code> will
  70.      * be set to true.  Else <code>enabled</code> will
  71.      * be set to false.
  72.      *
  73.      * @serial
  74.      * @see isEnabled()
  75.      * @see setEnabled()
  76.      */
  77.     boolean enabled = true;
  78.  
  79.     /**
  80.      * <code>label</code> is the label of a menu item.
  81.      * It can be any string.
  82.      *
  83.      * @serial
  84.      * @see getLabel()
  85.      * @see setLabel()
  86.      */
  87.     String label;
  88.  
  89.     /**
  90.      * This field indicates the command tha has been issued
  91.      * by a  particular menu item.
  92.      * By default the <code>actionCommand</code>
  93.      * is the label of the menu item, unless it has been
  94.      * set using setActionCommand.
  95.      *
  96.      * @serial
  97.      * @see setActionCommand()
  98.      * @see getActionCommand()
  99.      */
  100.     String actionCommand;
  101.  
  102.     /**
  103.      * The eventMask is ONLY set by subclasses via enableEvents.
  104.      * The mask should NOT be set when listeners are registered
  105.      * so that we can distinguish the difference between when
  106.      * listeners request events and subclasses request them.
  107.      *
  108.      * @serial
  109.      */
  110.     long eventMask;
  111.  
  112.     transient ActionListener actionListener;
  113.  
  114.     /**
  115.      * A sequence of key stokes that ia associated with
  116.      * a menu item.
  117.      * Note :in 1.1.2 you must use setActionCommand()
  118.      * on a menu item in order for its shortcut to
  119.      * work.
  120.      *
  121.      * @serial
  122.      * @see getShortcut()
  123.      * @see setShortcut()
  124.      * @see deleteShortcut()
  125.      */
  126.     private MenuShortcut shortcut = null;
  127.  
  128.     private static final String base = "menuitem";
  129.     private static int nameCounter = 0;
  130.  
  131.     /*
  132.      * JDK 1.1 serialVersionUID
  133.      */
  134.     private static final long serialVersionUID = -21757335363267194L;
  135.  
  136.     /**
  137.      * Constructs a new MenuItem with an empty label and no keyboard
  138.      * shortcut.
  139.      * @since    JDK1.1
  140.      */
  141.     public MenuItem() {
  142.     this("", null);
  143.     }
  144.  
  145.     /**
  146.      * Constructs a new MenuItem with the specified label
  147.      * and no keyboard shortcut. Note that use of "-" in
  148.      * a label is reserved to indicate a separator between
  149.      * menu items. By default, all menu items except for
  150.      * separators are enabled.
  151.      * @param       label the label for this menu item.
  152.      * @since       JDK1.0
  153.      */
  154.     public MenuItem(String label) {
  155.     this(label, null);
  156.     }
  157.  
  158.     /**
  159.      * Create a menu item with an associated keyboard shortcut.
  160.      * Note that use of "-" in a label is reserved to indicate
  161.      * a separator between menu items. By default, all menu
  162.      * items except for separators are enabled.
  163.      * @param       label the label for this menu item.
  164.      * @param       s the instance of <code>MenuShortcut</code>
  165.      *                       associated with this menu item.
  166.      * @since       JDK1.1
  167.      */
  168.     public MenuItem(String label, MenuShortcut s) {
  169.     this.label = label;
  170.         this.shortcut = s;
  171.     }
  172.  
  173.     /**
  174.      * Construct a name for this MenuComponent.  Called by getName() when
  175.      * the name is null.
  176.      */
  177.     String constructComponentName() {
  178.         synchronized (getClass()) {
  179.         return base + nameCounter++;
  180.     }
  181.     }
  182.  
  183.     /**
  184.      * Creates the menu item's peer.  The peer allows us to modify the
  185.      * appearance of the menu item without changing its functionality.
  186.      */
  187.     public void addNotify() {
  188.         synchronized (getTreeLock()) {
  189.         if (peer == null)
  190.             peer = Toolkit.getDefaultToolkit().createMenuItem(this);
  191.     }
  192.     }
  193.  
  194.     /**
  195.      * Gets the label for this menu item.
  196.      * @return  the label of this menu item, or <code>null</code>
  197.                        if this menu item has no label.
  198.      * @see     java.awt.MenuItem#setLabel
  199.      * @since   JDK1.0
  200.      */
  201.     public String getLabel() {
  202.     return label;
  203.     }
  204.  
  205.     /**
  206.      * Sets the label for this menu item to the specified label.
  207.      * @param     label   the new label, or <code>null</code> for no label.
  208.      * @see       java.awt.MenuItem#getLabel
  209.      * @since     JDK1.0
  210.      */
  211.     public synchronized void setLabel(String label) {
  212.     this.label = label;
  213.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  214.     if (peer != null) {
  215.         peer.setLabel(label);
  216.     }
  217.     }
  218.  
  219.     /**
  220.      * Checks whether this menu item is enabled.
  221.      * @see        java.awt.MenuItem#setEnabled
  222.      * @since      JDK1.0
  223.      */
  224.     public boolean isEnabled() {
  225.     return enabled;
  226.     }
  227.  
  228.     /**
  229.      * Sets whether or not this menu item can be chosen.
  230.      * @param      b  if <code>true</code>, enables this menu item;
  231.      *                       if <code>false</code>, disables it.
  232.      * @see        java.awt.MenuItem#isEnabled
  233.      * @since      JDK1.1
  234.      */
  235.     public synchronized void setEnabled(boolean b) {
  236.         enable(b);
  237.     }
  238.  
  239.     /**
  240.      * @deprecated As of JDK version 1.1,
  241.      * replaced by <code>setEnabled(boolean)</code>.
  242.      */
  243.     public synchronized void enable() {
  244.     enabled = true;
  245.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  246.     if (peer != null) {
  247.         peer.enable();
  248.     }
  249.     }
  250.  
  251.     /**
  252.      * @deprecated As of JDK version 1.1,
  253.      * replaced by <code>setEnabled(boolean)</code>.
  254.      */
  255.     public void enable(boolean b) {
  256.         if (b) {
  257.         enable();
  258.     } else {
  259.         disable();
  260.     }
  261.     }
  262.  
  263.     /**
  264.      * @deprecated As of JDK version 1.1,
  265.      * replaced by <code>setEnabled(boolean)</code>.
  266.      */
  267.     public synchronized void disable() {
  268.     enabled = false;
  269.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  270.     if (peer != null) {
  271.         peer.disable();
  272.     }
  273.     }
  274.  
  275.     /**
  276.      * Get the <code>MenuShortcut</code> object associated with this
  277.      * menu item,
  278.      * @return      the menu shortcut associated with this menu item,
  279.      *                   or <code>null</code> if none has been specified.
  280.      * @see         java.awt.MenuItem#setShortcut
  281.      * @since       JDK1.1
  282.      */
  283.     public MenuShortcut getShortcut() {
  284.         return shortcut;
  285.     }
  286.  
  287.     /**
  288.      * Set the <code>MenuShortcut</code> object associated with this
  289.      * menu item. If a menu shortcut is already associated with
  290.      * this menu item, it is replaced.
  291.      * @param       s  the menu shortcut to associate
  292.      *                           with this menu item.
  293.      * @see         java.awt.MenuItem#getShortcut
  294.      * @since       JDK1.1
  295.      */
  296.     public void setShortcut(MenuShortcut s) {
  297.         shortcut = s;
  298.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  299.     if (peer != null) {
  300.         peer.setLabel(label);
  301.     }
  302.     }
  303.  
  304.     /**
  305.      * Delete any <code>MenuShortcut</code> object associated
  306.      * with this menu item.
  307.      * @since      JDK1.1
  308.      */
  309.     public void deleteShortcut() {
  310.         shortcut = null;
  311.     MenuItemPeer peer = (MenuItemPeer)this.peer;
  312.     if (peer != null) {
  313.         peer.setLabel(label);
  314.     }
  315.     }
  316.  
  317.     /*
  318.      * Delete a matching MenuShortcut associated with this MenuItem.
  319.      * Used when iterating Menus.
  320.      */
  321.     void deleteShortcut(MenuShortcut s) {
  322.         if (s.equals(shortcut)) {
  323.             shortcut = null;
  324.             MenuItemPeer peer = (MenuItemPeer)this.peer;
  325.             if (peer != null) {
  326.                 peer.setLabel(label);
  327.             }
  328.         }
  329.     }
  330.  
  331.     /*
  332.      * Post an ActionEvent to the target (on
  333.      * keydown).  Returns true if there is an associated
  334.      * shortcut.
  335.      */
  336.     boolean handleShortcut(KeyEvent e) {
  337.         MenuShortcut s = new MenuShortcut(e.getKeyCode(),
  338.                              (e.getModifiers() & InputEvent.SHIFT_MASK) > 0);
  339.         if (s.equals(shortcut) && enabled) {
  340.             // MenuShortcut match -- issue an event on keydown.
  341.             if (e.getID() == KeyEvent.KEY_PRESSED) {
  342.                 Toolkit.getEventQueue().postEvent(
  343.                           new ActionEvent(this, ActionEvent.ACTION_PERFORMED,
  344.                                           actionCommand));
  345.             } else {
  346.                 // silently eat key release.
  347.             }
  348.             return true;
  349.     }
  350.         return false;
  351.     }
  352.  
  353.     MenuItem getShortcutMenuItem(MenuShortcut s) {
  354.         return (s.equals(shortcut)) ? this : null;
  355.     }
  356.  
  357.     /**
  358.      * Enables event delivery to this menu item for events
  359.      * to be defined by the specified event mask parameter
  360.      * <p>
  361.      * Since event types are automatically enabled when a listener for
  362.      * that type is added to the menu item, this method only needs
  363.      * to be invoked by subclasses of <code>MenuItem</code> which desire to
  364.      * have the specified event types delivered to <code>processEvent</code>
  365.      * regardless of whether a listener is registered.
  366.      * @param       eventsToEnable the event mask defining the event types.
  367.      * @see         java.awt.MenuItem#processEvent
  368.      * @see         java.awt.MenuItem#disableEvents
  369.      * @see         java.awt.Component#enableEvents
  370.      * @since       JDK1.1
  371.      */
  372.     protected final void enableEvents(long eventsToEnable) {
  373.         eventMask |= eventsToEnable;
  374.     }
  375.  
  376.     /**
  377.      * Disables event delivery to this menu item for events
  378.      * defined by the specified event mask parameter.
  379.      * @param       eventsToDisable the event mask defining the event types.
  380.      * @see         java.awt.MenuItem#processEvent
  381.      * @see         java.awt.MenuItem#enableEvents
  382.      * @see         java.awt.Component#disableEvents
  383.      * @since       JDK1.1
  384.      */
  385.     protected final void disableEvents(long eventsToDisable) {
  386.         eventMask &= ~eventsToDisable;
  387.     }
  388.  
  389.     /**
  390.      * Sets the command name of the action event that is fired
  391.      * by this menu item.
  392.      * <p>
  393.      * By default, the action command is set to the label of
  394.      * the menu item.
  395.      * @param       command   the action command to be set
  396.      *                                for this menu item.
  397.      * @see         java.awt.MenuItem#getActionCommand
  398.      * @since       JDK1.1
  399.      */
  400.     public void setActionCommand(String command) {
  401.         actionCommand = command;
  402.     }
  403.  
  404.     /**
  405.      * Gets the command name of the action event that is fired
  406.      * by this menu item.
  407.      * @see         java.awt.MenuItem#setActionCommand
  408.      * @since       JDK1.1
  409.      */
  410.     public String getActionCommand() {
  411.         return (actionCommand == null? label : actionCommand);
  412.     }
  413.  
  414.     /**
  415.      * Adds the specified action listener to receive action events
  416.      * from this menu item.
  417.      * If l is null, no exception is thrown and no action is performed.
  418.      *
  419.      * @param      l the action listener.
  420.      * @see        java.awt.event.ActionEvent
  421.      * @see        java.awt.event.ActionListener
  422.      * @see        java.awt.MenuItem#removeActionListener
  423.      * @since      JDK1.1
  424.      */
  425.     public synchronized void addActionListener(ActionListener l) {
  426.     if (l == null) {
  427.         return;
  428.     }
  429.     actionListener = AWTEventMulticaster.add(actionListener, l);
  430.         newEventsOnly = true;
  431.     }
  432.  
  433.     /**
  434.      * Removes the specified action listener so it no longer receives
  435.      * action events from this menu item.
  436.      * If l is null, no exception is thrown and no action is performed.
  437.      *
  438.      * @param      l the action listener.
  439.      * @see        java.awt.event.ActionEvent
  440.      * @see        java.awt.event.ActionListener
  441.      * @see        java.awt.MenuItem#addActionListener
  442.      * @since      JDK1.1
  443.      */
  444.     public synchronized void removeActionListener(ActionListener l) {
  445.     if (l == null) {
  446.         return;
  447.     }
  448.     actionListener = AWTEventMulticaster.remove(actionListener, l);
  449.     }
  450.  
  451.     /**
  452.      * Processes events on this menu item. If the event is an
  453.      * instance of <code>ActionEvent</code>, it invokes
  454.      * <code>processActionEvent</code>, another method
  455.      * defined by <code>MenuItem</code>.
  456.      * <p>
  457.      * Currently, menu items only support action events.
  458.      * @param       e the event.
  459.      * @see         java.awt.MenuItem#processActionEvent
  460.      * @since       JDK1.1
  461.      */
  462.     protected void processEvent(AWTEvent e) {
  463.         if (e instanceof ActionEvent) {
  464.             processActionEvent((ActionEvent)e);
  465.         }
  466.     }
  467.  
  468.     // REMIND: remove when filtering is done at lower level
  469.     boolean eventEnabled(AWTEvent e) {
  470.         if (e.id == ActionEvent.ACTION_PERFORMED) {
  471.             if ((eventMask & AWTEvent.ACTION_EVENT_MASK) != 0 ||
  472.                 actionListener != null) {
  473.                 return true;
  474.             }
  475.             return false;
  476.         }
  477.         return super.eventEnabled(e);
  478.     }
  479.  
  480.     /**
  481.      * Processes action events occurring on this menu item,
  482.      * by dispatching them to any registered
  483.      * <code>ActionListener</code> objects.
  484.      * This method is not called unless action events are
  485.      * enabled for this component. Action events are enabled
  486.      * when one of the following occurs:
  487.      * <p><ul>
  488.      * <li>An <code>ActionListener</code> object is registered
  489.      * via <code>addActionListener</code>.
  490.      * <li>Action events are enabled via <code>enableEvents</code>.
  491.      * </ul>
  492.      * @param       e the action event.
  493.      * @see         java.awt.event.ActionEvent
  494.      * @see         java.awt.event.ActionListener
  495.      * @see         java.awt.MenuItem#enableEvents
  496.      * @since       JDK1.1
  497.      */
  498.     protected void processActionEvent(ActionEvent e) {
  499.         if (actionListener != null) {
  500.             actionListener.actionPerformed(e);
  501.         }
  502.     }
  503.  
  504.     /**
  505.      * Returns the parameter string representing the state of this menu
  506.      * item. This string is useful for debugging.
  507.      * @return  the parameter string of this menu item.
  508.      * @since   JDK1.0
  509.      */
  510.     public String paramString() {
  511.         String str = ",label=" + label;
  512.         if (shortcut != null) {
  513.             str += ",shortcut=" + shortcut;
  514.         }
  515.         return super.paramString() + str;
  516.     }
  517.  
  518.  
  519.     /* Serialization support.
  520.      */
  521.  
  522.     /**
  523.      * Menu item serialized data version.
  524.      *
  525.      * @serial
  526.      */
  527.     private int menuItemSerializedDataVersion = 1;
  528.  
  529.     /**
  530.      * Writes default serializable fields to stream.  Writes
  531.      * a list of serializable ItemListener(s) as optional data.
  532.      * The non-serializable ItemListner(s) are detected and
  533.      * no attempt is made to serialize them.
  534.      *
  535.      * @serialData Null terminated sequence of 0 or more pairs.
  536.      *             The pair consists of a String and Object.
  537.      *             The String indicates the type of object and
  538.      *             is one of the following :
  539.      *             itemListenerK indicating and ItemListener object.
  540.      *
  541.      * @see AWTEventMulticaster.save(ObjectOutputStream, String, EventListener)
  542.      * @see java.awt.Component.itemListenerK
  543.      */
  544.     private void writeObject(ObjectOutputStream s)
  545.       throws IOException
  546.     {
  547.       s.defaultWriteObject();
  548.  
  549.       AWTEventMulticaster.save(s, actionListenerK, actionListener);
  550.       s.writeObject(null);
  551.     }
  552.  
  553.     /**
  554.      * Read the ObjectInputStream and if it isnt null
  555.      * add a listener to receive item events fired
  556.      * by the Menu Item.
  557.      * Unrecognised keys or values will be Ignored.
  558.      * 
  559.      * @see removeActionListener()
  560.      * @see addActionListener()
  561.      */
  562.     private void readObject(ObjectInputStream s)
  563.       throws ClassNotFoundException, IOException
  564.     {
  565.       s.defaultReadObject();
  566.  
  567.       Object keyOrNull;
  568.       while(null != (keyOrNull = s.readObject())) {
  569.     String key = ((String)keyOrNull).intern();
  570.  
  571.     if (actionListenerK == key)
  572.       addActionListener((ActionListener)(s.readObject()));
  573.  
  574.     else // skip value for unrecognized key
  575.       s.readObject();
  576.       }
  577.     }
  578.  
  579.     /**
  580.      * Initialize JNI field and method IDs
  581.      */
  582.     private static native void initIDs();
  583. }
  584.